/*
 * @Author: hruomei
 * @Title: 网络请求/文件下载、上传
 * @Description: 基于 Promise 对象实现更简单的 request 使用方式，支持请求和响应拦截
 * @CreateTime: 2019/05/31
 * @LastUpDateTime: 2019/10/24
 * @Version: V1.01
 */

import $config from '@/workspaces/api/framework/config.js'
import $api from '@/workspaces/api/framework/api.js'
import $login from '@/workspaces/api/framework/login.js'
const $store = {
	lang : require('../../language/zh.js')
}
const DEV = process.env.NODE_ENV === 'development';
let isPopLogoutModal = false;
const lyRequest = {
	requestConfig: {
		baseUrl: $config.domain,
		header: {
			'Accept': 'application/json, text/javascript, */*; q=0.01'
		},
		method: "GET",
		dataType: "json",
		// 如设为json，会对返回的数据做一次 JSON.parse
		responseType: "text",
		sslVerify:false,
		success() {},
		fail() {}
	},

	// 根据项目编码获取子应用相对路径
	getSubAppUrl(url, menucode) {
		if ($config && $config.isEmmApp && menucode) {
			return `/${menucode}${url}`;
		}
		return url;
	},

	// 拦截器
	interceptor: {
		// 设置请求前拦截器
		request: (config) => {
			let curtoken = $api.getToken(),
				reqData = config.data,
				result = {
					success: false,
					msg: ''
				};

			// 判断参数格式
			// if ($api.isArray(reqData)) {
			// 	result.msg = 'data 参数格式不能为Array';
			// 	return result;
			// } else
             if ($api.isString(reqData)) {
				result.msg = 'data 参数格式不能为String';
				return result;
			}

			// 校验非法参数
			for (let i in reqData) {
				if (!lyRequest.notInject(reqData[i])) {
					result.msg = `提交的数据中不能包含${$config.injectRule}字符`;
					result.msg = result.msg.replace(/(\|)/g, "、");
					return result;
				}
			}
			let setGatewayParamRes = lyRequest.setGatewayParam(config, config.method.toUpperCase() == 'POST');
			if(!setGatewayParamRes) {
				return null;
			}

			config.header['Authorization'] = curtoken;
			if ($config.isInjectToken) {
				config.data['token'] = curtoken;
			}

			result.success = true;
			return result;
		},

		// 设置请求结束后拦截器
		response: (result) => {
			return lyRequest.translateRes(result)
		}
	},

	// 设置移动网关相关参数
	setGatewayParam(config, isPost, isInjectUserParam) {
		// 判断是否移动中台app,需要添加经过移动网关所携带的数据
		if ($config && $config.isEmmApp) {
			let md5Str = '', // Md5校验数据
				currentTime = new Date().getTime(),
				deviceId = $config.deviceId,
				urlRelativePath = $api.getUrlRelativePath(config.url),
				method = '',
				gatewayParam = null;

			// #ifdef APP-PLUS
			deviceId = plus.device.uuid; // 获取设备ID
			// #endif

			md5Str = $api.md5Encript(currentTime + deviceId + urlRelativePath);

			gatewayParam = {
				'_1': currentTime,
				'_2': md5Str,
				'procode': $config.proCode || 'emm'
			}

			// MP接口需要添加一元化相关的数据
			if (lyRequest.isMpApi(config.url) || isInjectUserParam) {
                Object.assign(gatewayParam, lyRequest.getMpParam());
			}

			if ($api.isString(isPost)) {
				method = isPost.toUpperCase();
			} else {
				method = isPost ? 'POST' : 'GET';
			}

			if (method === 'POST') {
				config.url = $api.setUrlParams(config.url, gatewayParam);
			} else {
				Object.assign(config.data, gatewayParam);
			}

			return true;
		}

		return true;
	},

	// 获取网关及一元化相关参数
	getGatewayUserParam(url) {
		let currentTime = new Date().getTime(),
			deviceId = $config.deviceId,
			urlRelativePath = $api.getUrlRelativePath(url);

		// #ifdef APP-PLUS
		deviceId = plus.device.uuid; // 获取设备ID
		// #endif

        let gatewayParam = {
            '_1': currentTime,
            '_2': $api.md5Encript(currentTime + deviceId + urlRelativePath), // Md5校验数据
			'procode': $config.proCode || 'emm'
        }

        Object.assign(gatewayParam, lyRequest.getMpParam());

		return gatewayParam;
	},

    // 获取一元化相关用户参数
    getMpParam() {
        const userInfo = $api.getUserInfo();

        if (userInfo) {
        	return {
        		'_user': lyRequest.isPVUser(userInfo) ? encodeURIComponent(userInfo.worknumber.trim()) : encodeURIComponent(userInfo.ly_loginname.trim()),
        		'_empid': encodeURIComponent(userInfo.worknumber.trim()),
        		'_mob': encodeURIComponent(userInfo.phone_number.trim()),
        		'_email': encodeURIComponent(userInfo.email.trim())
        	}
        }

        return null;
    },

	// 判断是否子应用的API，一元化所需参数
	isMpApi(url) {
		let mpApi = $config.mpApi || ['/mp/', 'wfengine', '/mp/org', '/upload/workflow/'];

		return mpApi.some(api => url.indexOf(api) != -1);
	},

	// 判断是否PV用户，如果是PV用户，_user取工号，否则取登录名
	isPVUser(userInfo) {
		if (!userInfo) {
			return false;
		}

		return userInfo.role.some(role => role.ROLE_NAME.indexOf('PV') != -1);
	},

	// 防止注入
	notInject(str) {
		if (!$config.injectRule) return true;

		// 字符串中的关键字更具需要添加
		let injectArray = $config.injectRule.split('|');

		str = str != null ? str.toString().toUpperCase().trim() : '';

		for (let i in injectArray) {
			if (str.indexOf(injectArray[i]) > -1) {
				return false;
			}
		}

		return true;
	},

	// 注销登录
	logout(message) {
		// 如果已经弹出弹框,不重复弹出
		if(isPopLogoutModal) return;

		let pages = getCurrentPages(),
			route = pages.length > 0 ? pages[pages.length - 1].route : void 0;

		isPopLogoutModal = true;

		if (route && route.indexOf('login/login') != -1) {
            // 避免在登录页接收不到错误请求导致登录按钮加载状态无法结束
            uni.$emit('framework_logout_popMessage', message);

			// 如果当前已经在登录页,只弹框,不重新退出
			$api.showModalWithCloseButton(message.replace('${}', ''), () => {
				isPopLogoutModal = false;
			});
		} else {
			// 如果当前不在登录页,弹出提示框并退出
			$api.showModalWithCloseButton(message, () => {
				$login.forceLogout();
				isPopLogoutModal = false;
			});
		}
	},

	// 返回错误码处理逻辑，如token过期等，需要用户退出登录
	errCodeFilters: [
        // add by xiuxian 2020-07-29 拦截器增加token及用户过期的判断及处理
        {
        	code: 'l9900000001', // 用户过期
        	handle: function(message) {
        		// lyRequest.logout(message);
                uni.showToast({
                    title: message,
                    duration: 3000,
                    success:((res)=>{
                        setTimeout(()=>{
                            window.parent.location.pathname = '/workspaces/views/login/login';
                        },3000)
                    })
                });
        	}
        },
        {
        	code: 'l9900000002', // 用户过期
        	handle: function(message) {
                uni.showToast({
                    title: message,
                    duration: 3000,
                    success:((res)=>{
                        setTimeout(()=>{
                            window.parent.location.pathname = '/workspaces/views/login/login';
                        },3000)
                    })
                });
                // debugger
                // 提示
                    //提示成功后/隐藏提示
                     // 清空缓存
                     // 跳转登陆页面
        		// lyRequest.logout(message);
        	}
        },

        {
		code: '_3', // 用户过期
		handle: function(message) {
			lyRequest.logout(message);
		}
	},
    {
		code: '_102', // 当前请求API没有提交token
		handle: function(message) {
			lyRequest.logout(message);
		}
	}, {
		code: '_103', // token过期
		handle: function(message) {
			lyRequest.logout(message);
		}
	}, {
        code: 'o0100100006', // 用户已被禁用
        handle: function(message) {
        	lyRequest.logout(message);
        }
    }, {
        code: 'o0100100007', // 用户已被禁用
        handle: function(message) {
        	lyRequest.logout(message);
        }
    }, {
		code: 'o0100100008', // 用户已被锁定
		handle: function(message) {
			lyRequest.logout(message);
		}
	}, {
		code: 'o0100100012', // 强制修改密码
		handle: function(message) {
			if ($api.getUserInfo()) { // 有缓存信息,证明是登录后返回
				if(isPopLogoutModal) return;
				isPopLogoutModal = true;

				$api.showModalWithCloseButton(message, () => {
					// 避免在登录页接收不到错误请求导致登录按钮加载状态无法结束
					uni.$emit('framework_logout_popMessage', message);
					$login.forceResetPwd(message);

					isPopLogoutModal = false;
				});
			} else { // 否则是登录前返回
				uni.$emit('framework_login_forceUpdatePwd', message);
			}
		}
	}],

	// 根据返回的编码解析errorCode,并做统一的提示
	translateRes(result) {
		let analysisResult = null,
			lang = $store.lang,
			data = result.data;

		if ($api.isString(data)) {
			try {
				data = JSON.parse(data)
			} catch (e) {
				data = result.data;
			}
		}
		if(data.code == "110"){
			$api.showTip("用户过期，请重新登录");
			window.parent.location.pathname = '/workspaces/views/login/login';
		}else if(data.result =="10009021002"){
			$api.showTip("用户过期，请重新登录");
			window.parent.location.pathname = '/workspaces/views/login/login';
		}
		if (result.statusCode && data) {
			let translate,
				message = this.getMsg(data),
				result = this.getCode(data) + '';

			if (message) {
				let filter = lyRequest.errCodeFilters;

				translate = lang.errorCode[message] || message;

				if($config.errCodeFilters && Array.isArray($config.errCodeFilters) && $config.errCodeFilters.length > 0) {
					filter = [...filter, ...$config.errCodeFilters];
				}

				for (let i = 0, l = filter.length; i < l; i++) {
					if (filter[i].code === message) {
						filter[i].handle(translate);
						return null;
					}
				}
			} else {
				if (result === '1' || data.token) {
					translate = lang.requestSuccess;
				} else {
					translate = lang.requestErrMsg;
				}
			}

			if (result === '1' || data.token) {
				analysisResult = {
					success: true,
					message: translate
				};
			} else {
				analysisResult = {
					success: false,
					message: translate
				};
			}
		} else {
			let errMsg = '';

			if (result.errMsg) {
				errMsg = lang.errorCode[result.errMsg] || lang.requestErrMsg;
			} else {
				errMsg = lang.requestErrMsg;
			}

			analysisResult = {
				success: false,
				message: errMsg
			};
		}

		if (data && data.rows) {
			let rows = data.rows;
			if (!$api.isObject(rows) && !$api.isString(rows) && !$api.isNumber(rows)) {
				data.rows = JSON.parse(rows);
			}
		}

		analysisResult.data = data;
		uni.hideLoading();
		return $api.extend(result, analysisResult);
	},

	// 获取message字段
	getMsg(data) {
		if (data.hasOwnProperty('msg')) {
			return data['msg'];
		} else if (data.hasOwnProperty('message')) {
			return data['message'];
		} else if (data.hasOwnProperty('Message')) {
			return data['Message'];
		} else {
			return ''
		}
	},

	// 获取请求成功/失败标志
	getCode(data) {
		if (data.hasOwnProperty('result')) {
			return data['result'];
		} else if (data.hasOwnProperty('code')) {
			return data['code'];
		} else {
			return ''
		}
	},

	// 判断url是否为绝对路径
	posUrl(url) {
		return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
	},

	// 请求核心方法
	request(originalConf) {
		let _self = this,
			pages = getCurrentPages(),
			// 处理某些情况下请求响应延时,用户已经离开页面的情况
			route = pages.length > 0 ? pages[pages.length - 1].route : void 0;
		uni.showLoading({
			mask: true,
			title: "处理中...",
		});
		var f2bpmToken= "";
		if(author){
			var author= sessionStorage.getItem("f2bpmAuthor");
			author=eval("("+author+")");
			f2bpmToken=author.token;
		}
		if(originalConf.method.toUpperCase() == 'GET'){
			lyRequest.requestConfig.header = {
			    'Accept': "application/json, text/javascript, */*; q=0.01",
			    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8;",
				f2bpmToken: f2bpmToken
			};
			if(originalConf.headerType == "json"){
				lyRequest.requestConfig.header = {
				    'Accept': "application/json, text/javascript, */*; q=0.01",
					f2bpmToken: f2bpmToken
				};
			}
		}else{
			lyRequest.requestConfig.header = {
			    'Accept': "application/json, text/javascript, */*; q=0.01",
					f2bpmToken: f2bpmToken
			};
			if(originalConf.headerType == "form"){
				lyRequest.requestConfig.header = {
				    'Accept': "application/json, text/javascript, */*; q=0.01",
				    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8;",
					f2bpmToken: f2bpmToken
				};
			}
		}
		return new Promise((resolve, reject) => {
			$api.isNetworkCanUse(usable => {
				if (!usable) {
					$api.showTip('当前网络不给力哦~请检查您的网络状态');
					return new Promise(()=>{}); // 阻断当前promise，将进程转到新的Promise
				}

				let requestConfig = null,
					interceptorRes = null,
					// loading = true;
                    loading = false; //wxx  2020/09/21  修改请求loading

				originalConf.requestId = new Date().getTime();
				originalConf.route = route;
				requestConfig = $api.extend(true, {}, _self.requestConfig, originalConf);
				requestConfig.url = _self.posUrl(requestConfig.url) ? requestConfig.url : (requestConfig.baseUrl + requestConfig.url);

				if (requestConfig.data.hasOwnProperty('loading')) {
					loading = requestConfig.data.loading;
					delete requestConfig.data.loading;
				}

				requestConfig.complete = (response) => {
					let newResponse = null;

					loading && $api.hideLoading();
					response.requestId = requestConfig.requestId;
					response.route = requestConfig.route;
					response.url = requestConfig.url;
					newResponse = _self.interceptor.response(response);

					if (newResponse) {
						response = newResponse;
						// _reslog(response); // 统一的响应日志记录

						if (response.statusCode === 200) { // 成功
							return resolve(response);
						} else {
							response.message = response.message || '请求异常,请重试';
							return reject(response);
						}
					}
				}

				// 请求前拦截
				interceptorRes = _self.interceptor.request(requestConfig);

				if (interceptorRes) {
					if (!interceptorRes.success) {
						interceptorRes.message = interceptorRes.msg || '请求异常,请重试';

						return reject(interceptorRes);
					}
                    let titles = ''
                    if(requestConfig.method == "GET"){
                         titles = '正在加载...'
                    }else if(requestConfig.method == "POST"){
                         titles = '正在提交...'
                    }

					loading && $api.showLoading(titles);
					// _reqlog(requestConfig); // 统一的请求日志记录
					uni.request(requestConfig);
				}
			});
		});
	},

	get(url, data, headerType, options = {}) {
		options.url = url;
		options.data = data;
		options.headerType= headerType;
		options.method = 'GET';
		return this.request(options);
	},

	post(url, data, headerType, options = {}) {
		options.url = url;
		options.data = data;
		options.headerType= headerType;
		options.method = 'POST';
		return this.request(options);
	},

	put(url, data, headerType, options = {}) {
		options.url = url;
		options.data = data;
		options.headerType= headerType;
		options.method = 'PUT';
		return this.request(options);
	},

	delete(url, data, headerType, options = {}) {
		options.url = url;
		options.data = data;
		options.headerType= headerType;
		options.method = 'DELETE';
		return this.request(options);
	},

	// 上传文件,vcategory文件夹（如果是绝对路径，则取绝对路径），tempFilePath文件路径，param参数
	uploadFile(vcategory, tempFilePath, param, fileName = 'uploadfile') {
		let fileUrl = vcategory.indexOf('/') == -1 ? `/lyapp/file/fileupload/${vcategory}/upload.do` : vcategory,
			config = {
				url: this.posUrl(fileUrl) ? fileUrl : `${$config.domain}${fileUrl}`
			},
			uploadConf = null;

		// 移动中台网关及工作流参数处理
		lyRequest.setGatewayParam(config, true);
		uploadConf = {
			url: config.url,
			filePath: tempFilePath,
			name: fileName,
			header: {
				Authorization: $api.getToken()
			},
			formData: param
		}

		return new Promise((resolve, reject) => {
			uploadConf.complete = result => {
				$api.hideLoading();

				if (result.statusCode && result.statusCode == 200) {
					return resolve(this.translateRes(result));
				} else {
					let errorMsg = result.errMsg;

					if (errorMsg.indexOf('timeout') != -1) errorMsg = '请求超时';

					result.message = errorMsg;
					return reject(result);
				}
			}


			$api.showLoading();

			uni.uploadFile(uploadConf);
		});
	},

	// 文件下载，路径可以是绝对路径或相对路径,obj:{loading:true/false}
	downloadFile(url, obj) {
		let _self = this,
			isPost = obj && obj.hasOwnProperty('isPost') ? obj.isPost : true,
			isInjectUserParam = obj && obj.hasOwnProperty('isInjectUserParam') ? obj.isInjectUserParam : void 0,
			config = {
				url: this.posUrl(url) ? url : `${$config.domain}${url}`
			},
			downloadConf = null,
			loading = true;

		// 移动中台网关及工作流参数处理
		lyRequest.setGatewayParam(config, isPost, isInjectUserParam);
		downloadConf = {
			url: config.url,
			header: {
				Authorization: $api.getToken()
			}
		}

		return new Promise((resolve, reject) => {
			downloadConf.complete = function(result) {

				loading && $api.hideLoading();

				if (result.statusCode && result.statusCode == 200) {
					let resolveRes = {
						statusCode: result.statusCode,
						data: {
							result: '1',
							filePath: result.tempFilePath
						}
					};

					return resolve(_self.translateRes(resolveRes));
				} else {
					let errorMsg = result.errMsg;

					result.message = '请求异常';
					result.success = false;

					if (errorMsg.indexOf('timeout') != -1) {
						result.message = '请求超时'
					}

					if (result.statusCode == 404) {
						result.message = '找不到该资源'
					}

					return reject(result);
				}
			}

			if (obj && obj.hasOwnProperty("loading")) {
				loading = obj.loading;
				delete obj.loading;
			}

			loading && $api.showLoading();

			uni.downloadFile(downloadConf);
		});
	}
}

// 请求接口日志记录
function _reqlog(req) {
	// #ifdef APP-PLUS
	if (DEV) {
		console.log("【" + req.requestId + "】地址：" + JSON.stringify(req.url));

		if (req.data) {
			console.log("【" + req.requestId + "】参数：" + JSON.stringify(req.data));
		}
	}
	// #endif
}

// 响应接口日志记录
function _reslog(res) {
	let _statusCode = res.statusCode;
	// #ifdef APP-PLUS
	if (DEV) {
		if (_statusCode == 200) {
			console.log("【" + res.requestId + "】成功：" + JSON.stringify(res));
		} else {
			console.error("【" + res.requestId + "】失败：", JSON.stringify(res));
		}
	}
	// #endif

	// #ifndef APP-PLUS
	if (_statusCode !== 200) {
		console.error(res.message, res);
	}
	// #endif
}

export default lyRequest;
